package com.itita.ww2.game.user.payment;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang3.StringUtils;

import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.itita.ww2.core.WW2Exception;
import com.itita.ww2.data.shop.PaymentConfig;
import com.itita.ww2.data.shop.PaymentConfig.Category;
import com.itita.ww2.data.shop.PaymentConfig.Type;
import com.itita.ww2.enums.WW2ExceptionCode;
import com.itita.ww2.game.alliance.AllianceService;
import com.itita.ww2.game.enums.ContributeType;
import com.itita.ww2.game.user.UserRewardDispatch.RewardType;
import com.itita.ww2.game.user.UserService;
import com.itita.ww2.model.enums.ResourceType;
import com.itita.ww2.model.user.UserProfile;
import com.itita.ww2.redis.RedisUtil;
import com.itita.ww2.redis.cache.Table;
import com.smartfoxserver.v2.entities.data.ISFSObject;
import com.smartfoxserver.v2.entities.data.SFSObject;

public class UserPayManager {
	private UserProfile userProfile;
	private Table table;
	//
	private Map<String, String> itemMap;
	private MonthlyCardUtil monthlyCardUtil;

	public UserPayManager(UserProfile userProfile) {
		this.userProfile = userProfile;
		this.table = UserService.getInstance().getCacheUserDataTable();
		this.itemMap = new HashMap<>();
		this.monthlyCardUtil = new MonthlyCardUtil(userProfile);
	}

	public ISFSObject onPayment(String sku) throws WW2Exception {
		if (!canBuy(sku)) {
			throw new WW2Exception(WW2ExceptionCode.BUY_LIMIT);
		}
		addPayItem(sku);

		ISFSObject obj = SFSObject.newInstance();
		obj.putUtfString("sku", sku);
		obj.putBool("first", isFirstPay(sku));

		Category category = PaymentConfig.getCategory(sku);
		switch (category) {
		case GOLD:
			{
				ISFSObject resObj = SFSObject.newInstance();
				resObj.putInt(ResourceType.GOLD.getValue(), PaymentConfig.getGoldCountBySKU(sku));
				AllianceService.onContribute(userProfile, resObj, ContributeType.PAYMENT);
			}
			break;
		case MONTHLY_CARD:
			{
				// 检查续费状态
				boolean isRenewals = monthlyCardUtil.checkRenewalsAndAddPayItem(sku);
				obj.putBool("renewals", isRenewals);
			}
			break;
		default:
			break;
		}
		ISFSObject backObj = userProfile.getRewardManager().onReward(RewardType.PAYMENT, obj);
		backObj.putSFSObject("payItems", getPaylistAsSFSObject());
		backObj.putUtfString("sku", sku);
		return backObj;
	}

	private boolean canBuy(String sku) {
		if (PaymentConfig.getType(sku) == Type.INFINITY) {
			return true;
		}
		return getPayCount(sku) < PaymentConfig.getLimit(sku);
	}

	private void addPayItem(String sku) {
		itemMap.put(sku, String.valueOf(getPayCount(sku) + 1));
		update();
	}

	private int getPayCount(String sku) {
		String cStr = itemMap.get(sku);
		int count = 0;
		if (StringUtils.isNotBlank(cStr)) {
			count = Integer.valueOf(cStr);
		}
		return count;
	}

	private boolean isFirstPay(String sku) {
		return getPayCount(sku) == 0;
	}

	public ISFSObject getPaylistAsSFSObject() {
		ISFSObject ref = SFSObject.newInstance();
		for (Entry<String, String> entry : itemMap.entrySet()) {
			ref.putInt(entry.getKey(), Integer.valueOf(entry.getValue()));
		}
		return ref;
	}

	private void update() {
		String itemStr = Joiner.on('|').withKeyValueSeparator(":").join(itemMap);
		this.table.setValue(RedisUtil.genericKey(userProfile.getUid()), "payItems", itemStr);
	}

	public void initialize() {
		String itemStr = this.table.getValue(RedisUtil.genericKey(userProfile.getUid()), "payItems");
		if (StringUtils.isBlank(itemStr) || StringUtils.equals(itemStr, "null")) {
			itemMap.clear();
		} else {
			itemMap = new HashMap<>(Splitter.on('|').withKeyValueSeparator(':').split(itemStr));
		}
	}

	public final MonthlyCardUtil getMonthlyCardUtil() {
		return monthlyCardUtil;
	}
}
